/*
 * Douglas Hiura Longo, 14 de Setembro de 2010.
 * 
 * twitter.com/douglashiura
 * java.inf.ufsc.br/dh
 * douglashiura.blogspot.com
 * douglashiura.parprimo.com
 * douglashiura@gmail.com
 * */
package net.douglashiura.picon;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

final public class PiconStore {
	private Map<String, Object> estoque = new HashMap<String, Object>();
	private List<Link> referencias = new ArrayList<Link>();

	PiconStore() {
	}

	public static PiconStore build(Class<?> getClass) throws IOException,
			ExceptionCompilacao {
		String picoName = getClass.getSimpleName() + ".picon";
		return build(getClass.getResource(picoName));
	}

	public static PiconStore build(URL resource) throws IOException,
			ExceptionCompilacao {
		InputStream input = resource.openStream();
		byte[] arquivo = new byte[input.available()];
		input.read(arquivo);
		input.close();
		return Picon.build(new ArrayDeque<Toke>(new Tokenizador(new String(
				arquivo)).getTokes()));
	}

	public static PiconStore build(Class<?> getClass, String... nameInPath)
			throws IOException, ExceptionCompilacao {

		List<String> filesPicon = new ArrayList<String>();
		filesPicon.add(getClass.getSimpleName());
		for (String string : nameInPath) {
			filesPicon.add(string);
		}
		StringBuffer all = new StringBuffer();
		for (String string2 : filesPicon) {
			InputStream input = getClass
					.getResourceAsStream(string2 + ".picon");
			byte[] arquivo = new byte[input.available()];
			input.read(arquivo);
			input.close();
			all.append(new String(arquivo));
		}
		return Picon.build(new ArrayDeque<Toke>(new Tokenizador(all.toString())
				.getTokes()));
	}

	public void add(String uid, Object t) {
		estoque.put(uid, t);
	};

	public void addReferencia(Link link) {
		referencias.add(link);
	}

	@SuppressWarnings("unchecked")
	public <Y> Y get(String uid) {
		return (Y) estoque.get(uid);
	}

	void soldar() throws ExceptionCompilacao {
		for (Link link : referencias) {
			try {
				link.processar((Map<String, Object>) estoque);
			} catch (Exception e) {
				throw new ExceptionCompilacao(e, link.getToke());
			}
		}
	}

	@SuppressWarnings("unchecked")
	public <Y> List<Y> list(Class<Y> classe) {
		List<Y> lista = new ArrayList<Y>();
		for (Object t : estoque.values()) {
			if (classe.equals(t.getClass())) {
				lista.add((Y) t);
			}
		}
		return lista;
	}

	public <Y> Y get(String uid, Class<Y> klass) {
		return get(uid);
	}

	public Map<String, Object> getStore() {
		return estoque;
	}

}
